﻿
#include "kodes.h"
#include "hsystem.h"
#include "u_ux_table.h"
#include <boost/assert.hpp>


set<uint32> ElHSys::kie_ux_set;
set<uint32> ElHSys::kie_UX_set;
static_assert(sizeof(kie_ux)/sizeof(*kie_ux) > 0, "u/ux table malplena!");

ElHSys::ElHSys(Signaro baseSig)
: buf_(boost::circular_buffer<wchar_t>(3))
{
  BOOST_ASSERT(buf_.capacity() == 3);

  baseSignaro_ = LegoKonverto::getBySignaro(baseSig);
  BOOST_ASSERT(baseSignaro_);

  if (kie_ux_set.empty())
  {
    for (size_t i=0; i<sizeof(kie_ux)/sizeof(*kie_ux); i++)
      kie_ux_set.insert(unuigi(kie_ux[i].c1, kie_ux[i].c3));
      
    for (size_t i=0; i<sizeof(kie_UX)/sizeof(*kie_UX); i++)
      kie_UX_set.insert(unuigi(kie_UX[i].c3, kie_UX[i].c1));
  }
}

ElHSys::~ElHSys()
{
  delete baseSignaro_;
}

void ElHSys::setStream(istream *s)
{
  BOOST_ASSERT(buf_.empty());
  buf_.clear();
  BOOST_ASSERT(baseSignaro_);
  baseSignaro_->setStream(s);
}

uint32_t ElHSys::unuigi(wchar_t c1, wchar_t c2)
{
  const static wstring tmp(L"AaBbCcĈĉDdEeFfGgĜĝHhĤĥIiJjĴĵKkLlMmNnOoPpRrSsŜŝTtUuŬŭVvZz");
  if (wstring::npos == tmp.find_first_of(c1))
    c1 = ' ';
  if (wstring::npos == tmp.find_first_of(c2))
    c2 = ' ';
  return c2 + (uint32_t(c1) << 16);
}


wchar_t ElHSys::doni()
{
  while (buf_.size() < 3)
  {
    wchar_t c = baseSignaro_->doni();
    if (!c)
      break;
    buf_.push_back(c);
  }

  if (buf_.size() == 3)
  {
    if (buf_[2] == 'h' || buf_[2] == 'H')
    {
      switch (buf_[1])
      {
      case 'c':
        buf_.pop_back();
        buf_[1] = 0x0109;
        break;
      case 'C':
        buf_.pop_back();
        buf_[1] = 0x0108;
        break;
      case 'g': 
        buf_.pop_back();
        buf_[1] = 0x011D;
        break;
      case 'G': 
        buf_.pop_back();
        buf_[1] = 0x011C;
        break;
      case 'h': 
        buf_.pop_back();
        buf_[1] = 0x0125;
        break;
      case 'H': 
        buf_.pop_back();
        buf_[1] = 0x0124;
        break;
      case 'j': 
        buf_.pop_back();
        buf_[1] = 0x0135;
        break;
      case 'J': 
        buf_.pop_back();
        buf_[1] = 0x0134;
        break;
      case 's': 
        buf_.pop_back();
        buf_[1] = 0x015D;
        break;
      case 'S': 
        buf_.pop_back();
        buf_[1] = 0x015C;
        break;
      }
    }
  }

  if (buf_.size() == 3)
  {
    if (buf_[1] == 'u')
    {
      if (kie_ux_set.count(unuigi(buf_[0], buf_[2])))
        buf_[1] = 0x016D;
    } 
    if (buf_[1] == 'U')
    {
      if (kie_UX_set.count(unuigi(buf_[0], buf_[2])))
        buf_[1] = 0x016C;
    }
  }

  wchar_t res = 0;
  if (!buf_.empty())
  {
    res = buf_.front();
    buf_.pop_front();
  }
  return res;
}












AlHSys::AlHSys(Signaro baseSig)
{
  baseSignaro_ = ScriboKonverto::getBySignaro(baseSig);
  BOOST_ASSERT(baseSignaro_);
}

AlHSys::~AlHSys()
{
  delete baseSignaro_;
}

void AlHSys::setStream(ostream *s)
{
  BOOST_ASSERT(baseSignaro_);
  baseSignaro_->setStream(s);
}

void AlHSys::meti(wchar_t c)
{
  switch (c)
  {
    case 0x0109:
      baseSignaro_->meti('c');
      baseSignaro_->meti('h');
      break;
    case 0x0108:
      baseSignaro_->meti('C');
      baseSignaro_->meti('H');
      break;
    case 0x011D:
      baseSignaro_->meti('g');
      baseSignaro_->meti('h');
      break;
    case 0x011C:
      baseSignaro_->meti('G');
      baseSignaro_->meti('H');
      break;
    case 0x0125:
      baseSignaro_->meti('h');
      baseSignaro_->meti('h');
      break;
    case 0x0124:
      baseSignaro_->meti('H');
      baseSignaro_->meti('H');
      break;
    case 0x0135:
      baseSignaro_->meti('j');
      baseSignaro_->meti('h');
      break;
    case 0x0134:
      baseSignaro_->meti('J');
      baseSignaro_->meti('H');
      break;
    case 0x015D:
      baseSignaro_->meti('s');
      baseSignaro_->meti('h');
      break;
    case 0x015C:
      baseSignaro_->meti('S');
      baseSignaro_->meti('H');
      break;
    case 0x016D:
      baseSignaro_->meti('u');
      break;
    case 0x016C:
      baseSignaro_->meti('U');
      break;
    default:
      baseSignaro_->meti(c);
  }
}

